package com.evildog.workspace.dependencies.mybatis.base;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.IService;
import com.evildog.workspace.common.util.WsAssert;
import com.evildog.workspace.dependencies.mybatis.enums.MybatisCustomExceptionDesc;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 封装对关联link表的操作 (remove getLinkList getLinkIdList)
 */
@Service
public class TableLinkService {

    //             remove                //

    /**
     * 根据其中一个关联id删除关联表
     *
     * @param iService IService 通用service
     * @param queryFunction SFunction link对应的getter
     * @param linkId   其中一个linkID
     */
    public <T> boolean removeByLinkId(IService<T> iService, SFunction<T, ?> queryFunction, Serializable linkId) {
        return iService.remove(Wrappers.<T>lambdaQuery()
                .eq(queryFunction, linkId)
        );
    }

    /**
     * 根据其中一个关联id删除关联表
     *
     * @param baseMapper baseMapper 通用baseMapper
     * @param queryFunction   SFunction link对应的getter
     * @param linkId     其中一个linkID
     */
    public <T> int removeByLinkId(BaseMapper<T> baseMapper, SFunction<T, ?> queryFunction, Serializable linkId) {
        return baseMapper.delete(Wrappers.<T>lambdaQuery()
                .eq(queryFunction, linkId)
        );
    }

    /**
     * 根据其中一个关联id删除关联表
     *
     * @param iService  IService 通用service
     * @param queryFunctions SFunction link对应的getter
     * @param linkIds   需要删除的linkID
     */
    public <T> boolean removeByLinkId(IService<T> iService, SFunction<T, ?>[] queryFunctions, Serializable[] linkIds) {
        LambdaQueryWrapper<T> lambdaQueryWrapper = getLambdaQueryWrapper(queryFunctions, linkIds);
        return iService.remove(lambdaQueryWrapper);
    }

    /**
     * 根据其中一个关联id删除关联表
     *
     * @param baseMapper baseMapper baseMapper
     * @param queryFunctions  SFunction link对应的getter
     * @param linkIds    需要删除的linkID
     */
    public <T> int removeByLinkId(BaseMapper<T> baseMapper, SFunction<T, ?>[] queryFunctions, Serializable[] linkIds) {
        LambdaQueryWrapper<T> lambdaQueryWrapper = getLambdaQueryWrapper(queryFunctions, linkIds);
        return baseMapper.delete(lambdaQueryWrapper);
    }


    //             getLinkIdList                //

    /**
     * 根据其中一个关联id查询出另外一个linkId的集合
     *
     * @param iService             iService iService
     * @param resultLinkIdFunction 结果集linkId对应的getter
     * @param queryFunction        查询用的linkId对应的getter
     * @param queryLinkId          查询用的linkId
     * @param <T>                  Mybatis plus 的通用查询
     * @param <R>                  需要返回的类型
     */
    public <T, R> List<R> getLinkIdList(IService<T> iService, SFunction<T, R> resultLinkIdFunction, SFunction<T, R> queryFunction, Serializable queryLinkId) {
        LambdaQueryWrapper<T> lambdaQueryWrapper = Wrappers.<T>lambdaQuery()
                .select(resultLinkIdFunction)
                .eq(queryFunction, queryLinkId);

        return iService.list(lambdaQueryWrapper).stream().map(resultLinkIdFunction).collect(Collectors.toList());
    }


    /**
     * 根据其中一个关联id查询出另外一个linkId的集合
     *
     * @param iService             iService iService
     * @param resultLinkIdFunction 结果集linkId对应的getter
     * @param queryFunction        查询用的linkId对应的getter
     * @param queryLinkIds          查询用的linkId
     * @param <T>                  Mybatis plus 的通用查询
     * @param <R>                  需要返回的类型
     */
    public <T, R> List<R> getLinkIdList(IService<T> iService, SFunction<T, R> resultLinkIdFunction, SFunction<T, R> queryFunction, Collection<?> queryLinkIds) {
        if(queryLinkIds.isEmpty()){
            return new ArrayList<>();
        }
        LambdaQueryWrapper<T> lambdaQueryWrapper = Wrappers.<T>lambdaQuery()
                .select(resultLinkIdFunction)
                .in(queryFunction, queryLinkIds);

        return iService.list(lambdaQueryWrapper).stream().map(resultLinkIdFunction).collect(Collectors.toList());
    }

    /**
     * 根据其中一个关联id查询出另外一个linkId的集合
     *
     * @param baseMapper           baseMapper baseMapper
     * @param resultLinkIdFunction 结果集linkId对应的getter
     * @param queryFunction        查询用的linkId对应的getter
     * @param queryLinkId          查询用的linkId
     * @param <T>                  Mybatis plus 的通用查询
     * @param <R>                  需要返回的类型
     */
    public <T, R> List<R> getLinkIdList(BaseMapper<T> baseMapper, SFunction<T, R> resultLinkIdFunction, SFunction<T, R> queryFunction, Serializable queryLinkId) {
        LambdaQueryWrapper<T> lambdaQueryWrapper = Wrappers.<T>lambdaQuery()
                .select(resultLinkIdFunction)
                .eq(queryFunction, queryLinkId);

        return baseMapper.selectList(lambdaQueryWrapper).stream().map(resultLinkIdFunction).collect(Collectors.toList());
    }

    /**
     * 根据其中一个关联id查询出另外一个linkId的集合
     *
     * @param baseMapper           baseMapper baseMapper
     * @param resultLinkIdFunction 结果集linkId对应的getter
     * @param queryFunction        查询用的linkId对应的getter
     * @param queryLinkIds          查询用的linkId
     * @param <T>                  Mybatis plus 的通用查询
     * @param <R>                  需要返回的类型
     */
    public <T, R> List<R> getLinkIdList(BaseMapper<T> baseMapper, SFunction<T, R> resultLinkIdFunction, SFunction<T, R> queryFunction, Collection<?> queryLinkIds) {
        if(queryLinkIds.isEmpty()){
            return new ArrayList<>();
        }

        LambdaQueryWrapper<T> lambdaQueryWrapper = Wrappers.<T>lambdaQuery()
                .select(resultLinkIdFunction)
                .in(queryFunction, queryLinkIds);

        return baseMapper.selectList(lambdaQueryWrapper).stream().map(resultLinkIdFunction).collect(Collectors.toList());
    }


    //             getLinkList                //

    /**
     * 根据其中一个关联id查询出另外一个linkId的集合
     *
     * @param iService             iService iService
     * @param queryFunction        查询用的linkId对应的getter
     * @param queryLinkId          查询用的linkId
     * @param <T>                  Mybatis plus 的通用查询
     */
    public <T> List<T> getLinkList(IService<T> iService, SFunction<T, ?> queryFunction, Serializable queryLinkId) {
        LambdaQueryWrapper<T> lambdaQueryWrapper = Wrappers.<T>lambdaQuery()
                .eq(queryFunction, queryLinkId);

        return iService.list(lambdaQueryWrapper);
    }


    /**
     * 根据其中一个关联id查询出另外一个linkId的集合
     *
     * @param iService             iService iService
     * @param queryFunction        查询用的linkId对应的getter
     * @param queryLinkIds          查询用的linkId value
     * @param <T>                  Mybatis plus 的通用查询
     */
    public <T> List<T> getLinkList(IService<T> iService, SFunction<T, ?> queryFunction, Collection<?> queryLinkIds) {
        if(queryLinkIds.isEmpty()){
            return new ArrayList<>();
        }

        LambdaQueryWrapper<T> lambdaQueryWrapper = Wrappers.<T>lambdaQuery()
                .in(queryFunction, queryLinkIds);

        return iService.list(lambdaQueryWrapper);
    }

    /**
     * 根据其中一个关联id查询出另外一个linkId的集合
     *
     * @param baseMapper           baseMapper baseMapper
     * @param queryFunction        查询用的linkId对应的getter
     * @param queryLinkId          查询用的linkId
     * @param <T>                  Mybatis plus 的通用查询
     */
    public <T> List<T> getLinkList(BaseMapper<T> baseMapper, SFunction<T, ?> queryFunction, Serializable queryLinkId) {
        LambdaQueryWrapper<T> lambdaQueryWrapper = Wrappers.<T>lambdaQuery()
                .eq(queryFunction, queryLinkId);

        return baseMapper.selectList(lambdaQueryWrapper);
    }

    /**
     * 根据其中一个关联id查询出另外一个linkId的集合
     * @param <T>                  Mybatis plus 的通用查询
     * @param baseMapper           baseMapper baseMapper
     * @param queryFunction        查询用的linkId对应的getter
     * @param queryLinkIds          查询用的linkId
     */
    public <T> List<T> getLinkList(BaseMapper<T> baseMapper, SFunction<T, ?> queryFunction, Collection<?> queryLinkIds) {
        if(queryLinkIds.isEmpty()){
            return new ArrayList<>();
        }
        LambdaQueryWrapper<T> lambdaQueryWrapper = Wrappers.<T>lambdaQuery()
                .in(queryFunction, queryLinkIds);

        return baseMapper.selectList(lambdaQueryWrapper);
    }

    private <T> LambdaQueryWrapper<T> getLambdaQueryWrapper(SFunction<T, ?>[] functions, Serializable[] linkIds) {
        LambdaQueryWrapper<T> lambdaQueryWrapper = Wrappers.lambdaQuery();
        WsAssert.isTrue(functions.length == linkIds.length, MybatisCustomExceptionDesc.INVALID_LINK_REMOVE_IDS);

        for (int i = 0; i < functions.length; i++) {
            SFunction<T, ?> function = functions[i];
            Serializable linkId = linkIds[i];
            lambdaQueryWrapper.eq(function, linkId);

        }
        return lambdaQueryWrapper;
    }
}
